#include "MyTimer.h"


//定时器(输入捕获)测试程序   V1.0           修改日期：2025/6/10
//实现功能：使用TIMER0 CH0 (PA8)捕获TIMER2的PWM周期（测频率上限1KHZ）
//          并从UART0输出测频结果
//By:TAO XIN YU (陶鑫宇)


//初始化定时器0作为捕获端，ch0通道
void MyTimer0_init(void)
{
	//使能定时器引脚时钟
	rcu_periph_clock_enable(RCU_GPIOA);
	//使能定时器TIMER0时钟
	rcu_periph_clock_enable(RCU_TIMER0);
	
	//设置TIMER0_CHO引脚电气属性 复用悬空
	gpio_mode_set(GPIOA,GPIO_MODE_AF,GPIO_PUPD_NONE,TIMER0_CH0_PIN);
	//设置TIMER0_CHO引脚输出配置
	gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,TIMER0_CH0_PIN);
	//设置TIMER0_CHO引脚复用
	gpio_af_set(GPIOA,GPIO_AF_2,TIMER0_CH0_PIN);
	
	//声明TIMER0输入捕获配置结构体
	timer_ic_parameter_struct timer_icinitpara={0};
	//声明TIMER0参数配置结构体
	timer_parameter_struct timer_initpara={0};
	
	//TIMER0缺省配置，防止出现意外错误
	timer_deinit(TIMER0);
	//TIMER0时基缺省配置，防止出现意外错误
	timer_struct_para_init(&timer_initpara);
	
	//设置预分频器 
	timer_initpara.prescaler =7200-1;
	//边沿对齐模式
	timer_initpara.alignedmode=TIMER_COUNTER_EDGE;
	//向上计数模式
	timer_initpara.counterdirection=TIMER_COUNTER_UP;
	//配置重装载计数器最大值
	timer_initpara.period = 65535-1;
	//配置时钟源分频
	timer_initpara.clockdivision=TIMER_CKDIV_DIV1;
	//初始化TIMER0
	timer_init(TIMER0,&timer_initpara);
	
	//TIMER0输入捕获缺省配置，防止出现意外错误
	timer_channel_input_struct_para_init(&timer_icinitpara);
	//配置输入捕获极性 上升沿
	timer_icinitpara.icpolarity=TIMER_IC_POLARITY_RISING;
	//配置捕获通道 直连
	timer_icinitpara.icselection=TIMER_IC_SELECTION_DIRECTTI;
	//配置输入分频 不分频
	timer_icinitpara.icprescaler=TIMER_IC_PSC_DIV1;
	//配置输入滤波, 不滤波
	timer_icinitpara.icfilter=0x00;
	//初始化TIMER0 ch0通道输入捕获配置
	timer_input_pwm_capture_config(TIMER0, TIMER_CH_0, &timer_icinitpara);
	
	//使能影子寄存器
	timer_auto_reload_shadow_enable(TIMER0);
	//清除TIMER0中断标志位
	timer_interrupt_flag_clear(TIMER0, TIMER_INT_FLAG_CH0);
	//开启TIMER0 CH0中断
	timer_interrupt_enable(TIMER0, TIMER_INT_CH0);
	
	//使能TIMER0
	timer_enable(TIMER0);
	//使能TIMER0中断
	nvic_irq_enable(TIMER0_Channel_IRQn,2);
	
}



//初始化TIMER2
//参数： prescaler：			预分频器值
//参数： period：				重装载计数器值
//无返回值
void MyTimer2_init(unsigned int prescaler,unsigned int period)
{
	//使能定时器输出引脚时钟
	rcu_periph_clock_enable(RCU_GPIOA);
	//使能定时器输出引脚时钟
	rcu_periph_clock_enable(RCU_GPIOB);
	
	//******************************************************//
	//各通道GPIO设置
	
	//设置TIMER2_CHO引脚电气属性 复用悬空
	gpio_mode_set(GPIOA,GPIO_MODE_AF,GPIO_PUPD_NONE,TIMER2_CH0_PIN);
	//设置TIMER2_CHO引脚输出配置
	gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,TIMER2_CH0_PIN);
	//设置TIMER2_CHO引脚复用
	gpio_af_set(GPIOA,GPIO_AF_1,TIMER2_CH0_PIN);
	
	//设置TIMER2_CH1引脚电气属性 复用悬空
	gpio_mode_set(GPIOA,GPIO_MODE_AF,GPIO_PUPD_NONE,TIMER2_CH1_PIN);
	//设置TIMER2_CH1引脚输出配置
	gpio_output_options_set(GPIOA,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,TIMER2_CH1_PIN);
	//设置TIMER2_CH1引脚复用
	gpio_af_set(GPIOA,GPIO_AF_1,TIMER2_CH1_PIN);
	
	//设置TIMER2_CH2引脚电气属性 复用悬空
	gpio_mode_set(GPIOB,GPIO_MODE_AF,GPIO_PUPD_NONE,TIMER2_CH2_PIN);
	//设置TIMER2_CH2引脚输出配置
	gpio_output_options_set(GPIOB,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,TIMER2_CH2_PIN);
	//设置TIMER2_CH2引脚复用
	gpio_af_set(GPIOB,GPIO_AF_1,TIMER2_CH2_PIN);
	
	//设置TIMER2_CH3引脚电气属性 复用悬空
	gpio_mode_set(GPIOB,GPIO_MODE_AF,GPIO_PUPD_NONE,TIMER2_CH3_PIN);
	//设置TIMER2_CH3引脚输出配置
	gpio_output_options_set(GPIOB,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,TIMER2_CH3_PIN);
	//设置TIMER2_CH3引脚复用
	gpio_af_set(GPIOB,GPIO_AF_1,TIMER2_CH3_PIN);
	
	
	//声明TIMER2参数配置结构体
	timer_parameter_struct timer_initpara={0};
	//声明TIMER2输出比较控制结构体
	timer_oc_parameter_struct timer_ocinitpara={0};
	
	//开启定时器2时钟
	rcu_periph_clock_enable(RCU_TIMER2);
	
	//恢复缺省配置，以免出现不必要的错误
	timer_deinit(TIMER2);
	timer_struct_para_init(&timer_initpara);
	
	//配置预分频器
	timer_initpara.prescaler = prescaler-1;
	//配置对齐模式 边缘对齐
	timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
	//配置计数方向 向上计数
	timer_initpara.counterdirection = TIMER_COUNTER_UP;
	//配置重装载计数器最大值
	timer_initpara.period = period;
	//配置时钟分频
	timer_initpara.clockdivision  = TIMER_CKDIV_DIV1;
	//配置重复计数器
	timer_initpara.repetitioncounter= 0 ;
	//初始化时基单元
	timer_init(TIMER2,&timer_initpara);
	
	//配置输出比较单元
	//恢复缺省配置，以免出现不必要的错误
	timer_channel_output_struct_para_init(&timer_ocinitpara);
	
	//配置输出模式 捕获/比较使能
	timer_ocinitpara.outputstate=TIMER_CCX_ENABLE;
	//不使用互补输出
	timer_ocinitpara.outputnstate=TIMER_CCXN_DISABLE;
	//配置输出极性 高极性
	timer_ocinitpara.ocpolarity=TIMER_OC_POLARITY_HIGH;
	//配置互补输出极性 低极性
	timer_ocinitpara.ocnpolarity=TIMER_OCN_POLARITY_LOW;
	//配置输出空闲状态 低电平
	timer_ocinitpara.ocidlestate=TIMER_OC_IDLE_STATE_LOW;
	//配置互补输出空闲状态 高电平 
	timer_ocinitpara.ocnidlestate=TIMER_OCN_IDLE_STATE_HIGH;
	//定时器输出通道控制（全部）
	timer_channel_output_config(TIMER2,TIMER_CH_0,&timer_ocinitpara);
	timer_channel_output_config(TIMER2,TIMER_CH_1,&timer_ocinitpara);
	timer_channel_output_config(TIMER2,TIMER_CH_2,&timer_ocinitpara);
	timer_channel_output_config(TIMER2,TIMER_CH_3,&timer_ocinitpara);
	
	//定时器通道0输出比较值控制 100%
	timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,period);
	//定时器通道0输出模式控制 PWM0模式
	timer_channel_output_mode_config(TIMER2,TIMER_CH_0,TIMER_OC_MODE_PWM0);
	//定时器通道0影子寄存器使能/使能控制  失能
	timer_channel_output_shadow_config(TIMER2,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
	
	//定时器通道1输出比较值控制 75%
	timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,period/4*3);
	//定时器通道1输出模式控制 PWM0模式
	timer_channel_output_mode_config(TIMER2,TIMER_CH_1,TIMER_OC_MODE_PWM0);
	//定时器通道1影子寄存器使能/使能控制  失能
	timer_channel_output_shadow_config(TIMER2,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);
	
	//定时器通道2输出比较值控制 50%
	timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,period/4*2);
	//定时器通道2输出模式控制 PWM0模式
	timer_channel_output_mode_config(TIMER2,TIMER_CH_2,TIMER_OC_MODE_PWM0);
	//定时器通道2影子寄存器使能/使能控制  失能
	timer_channel_output_shadow_config(TIMER2,TIMER_CH_2,TIMER_OC_SHADOW_DISABLE);
	
	//定时器通道2输出比较值控制 25%
	timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_3,period/4*1);
	//定时器通道2输出模式控制 PWM0模式
	timer_channel_output_mode_config(TIMER2,TIMER_CH_3,TIMER_OC_MODE_PWM0);
	//定时器通道2影子寄存器使能/使能控制  失能
	timer_channel_output_shadow_config(TIMER2,TIMER_CH_3,TIMER_OC_SHADOW_DISABLE);
	
	//使能定时器
	timer_enable(TIMER2);
	
	
}

//TIMER0中断函数，用于测频
void TIMER0_Channel_IRQHandler(void)
{
	//声明测频状态变量
	static unsigned char ic_status=0;
	//声明第一边沿缓存值
	static unsigned int ic1_value=0;
	//声明第二边沿缓存值
	static unsigned int ic2_value=0;
	//声明计数差值
	static unsigned int count=0;
	//声明频率变量
	static float frequency = 0;
	
	//如果是ch0通道产生的中断
	if(SET == timer_interrupt_flag_get(TIMER0,TIMER_INT_FLAG_CH0))
	{
		//如果是第一边沿
		if(0 == ic_status)
		{
			//清空缓存值
			ic1_value=0;
			ic2_value=0;
			//读取此时的计数器值
			ic1_value = timer_channel_capture_value_register_read(TIMER0,TIMER_CH_0);
			//准备接收第二边沿
			ic_status=1;
		}
		//如果是第二边沿
		else 
		{
			//读取此时的计数器值
			ic2_value = timer_channel_capture_value_register_read(TIMER0,TIMER_CH_0);
			//获取两个边沿的差值
			count = ic2_value - ic1_value;
			//计算频率  频率 = （差值-1）*单次计数时间 取倒数
			frequency= 1/((float)(count-1) * 0.0001);
			//输出信息
			printf("\r\n");
			printf("ic1_value:%u\r\n",ic1_value);
			printf("ic2_value:%u\r\n",ic2_value);
			printf("count:%u\r\n",count);
			printf("frequency:%f\r\n",frequency);
			printf("\r\n");
			//清空计数器
			timer_counter_value_config(TIMER0,0);
			//结束本次测频
			ic_status=0;	
		}
		//清除中断标志位
		timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_CH0);
	}
}


